home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
pbspline.zip
/
bspline.c
next >
Wrap
C/C++ Source or Header
|
1994-05-10
|
5KB
|
216 lines
/* pov-bspline v1.0
*
* 10 May 1994, Michael Mittelstadt. (not responsible for ugly output)
*
* The spline algorithm is not of my own making, which is probably a
* Good Thing. This program does a pretty good approx. of a bspline
* and outputs povray code given x,y,z triplets.
*
* report all bugs and improvements to meek@alpha2.csd.uwm.edu
*
*/
#include <unistd.h>
#include <math.h>
#include <stdio.h>
#define VERSION 1.0
#define CONTROL_MAX 1000 /* change these to suit your whims (or ram) */
#define SPLINE_MAX 5000
int total, points, degree;
double thick;
short int include;
double rp[SPLINE_MAX][3];
double dots[CONTROL_MAX][3];
static double U[50];
/* A quick gopher search turned up this subroutine. -- MWM */
/* Returns a set of (m+1) spline curve points given a set of (n+1) control
* points. (t-1) is the degree of the polynomial used for the B-splines.
* Cubic polynomials (i.e., t=4) are usually sufficient. [3] designates
* (x,y,z). For a discussion of the spline curve algorithm, see the book
* ``Computer Graphics'', Donald Hearn and M. Pauline Baker, Prentice-Hall,
* 1986, pp. 200-2.
*/
void
spline(controlpoints, n, curvepoints, m, t)
double controlpoints[][3];
int n;
double curvepoints[][3];
int m;
int t;
{
int j, k;
double N(), temp, u;
for (j = 0; j <= n + t; j++) {
if (j < t)
U[j] = 0.0;
else if (t <= j && j <= n)
U[j] = j - t + 1;
else
U[j] = n - t + 2;
}
for (j = 0; j <= m; j++) {
u = ((double) j / m) * (n - t + 2 - .00000001);
curvepoints[j][0] = curvepoints[j][1] = curvepoints[j][2] = 0.0;
for (k = 0; k <= n; k++) {
temp = N(k, t, u);
curvepoints[j][0] += controlpoints[k][0] * temp;
curvepoints[j][1] += controlpoints[k][1] * temp;
curvepoints[j][2] += controlpoints[k][2] * temp;
}
}
}
static double
N(k, t, u)
int k;
int t;
double u;
{
double firstterm, secondterm;
if (t == 1)
if (U[k] <= u && u < U[k + 1])
return 1.0;
else
return 0.0;
if (U[k + t - 1] - U[k] < 1.0e-10) /* Test for zero with real #s */
firstterm = 0.0;
else
firstterm = ((u - U[k]) / (U[k + t - 1] - U[k])) * N(k, t - 1, u);
if (U[k + t] - U[k + 1] < 1.0e-10)
secondterm = 0.0;
else
secondterm = ((U[k + t] - u) / (U[k + t] - U[k + 1])) * N(k + 1, t - 1, u);
return firstterm + secondterm;
}
void
outputheader()
{
printf("/* File generated by pov-bspline v%1.1f */\n", VERSION);
printf("\n\ncamera { location <0,0,-10>");
printf("\n direction z up y right 4/3*x }");
printf("\n\nlight_source { <-1,1,-12> color rgb <1,1,1> }");
printf("\n\n#declare def_tex=texture {");
printf("\n pigment { color rgb <0.8,0.75,0.5> } }\n\n");
}
void
putsphere(punkt)
double punkt[3];
{
printf(" sphere { <%lf,%lf,%lf>,%lf }\n", punkt[0], punkt[1], punkt[2], thick);
}
void
putcone(punkt1, punkt2)
double punkt1[3], punkt2[3];
{
printf(" cone { <%lf,%lf,%lf>,%lf,<%lf,%lf,%lf>,%lf }\n",
punkt1[0], punkt1[1], punkt1[2], thick,
punkt2[0], punkt2[1], punkt2[2], thick);
}
int
snarfnumbers()
{
int i = 0;
while (!feof(stdin)) {
scanf("%lf %lf %lf", &dots[i][0], &dots[i][1], &dots[i][2]);
i++;
}
i -= 2;
fprintf(stderr, "Points input: %d\n\n", i + 1);
return (i);
}
void
outputstuff(total)
int total;
{
int i;
if (!include)
outputheader();
spline(dots, total, rp, (points * total), 3);
printf("#declare spline_obj = union {\n");
putsphere(rp[0]);
for (i = 1; i < (points * total) + 1; i++) {
putsphere(rp[i]);
putcone(rp[i - 1], rp[i]);
}
printf("} // spline_obj\n\n");
if (!include)
printf("\nobject { spline_obj texture { def_tex } }\n\n");
}
main(argc, argv)
int argc;
char **argv;
{
int c;
extern char *optarg;
thick = 1.0;
points = 5;
degree = 4;
include = 0;
while (1) {
c = getopt(argc, argv, "it:n:hp:");
if (c == -1)
break;
if (c == 'h') {
printf("syntax: bspline [options] < infile > whatever.pov\n");
printf("version: %1.1f\n", VERSION);
printf("options: -h - This help.\n");
printf(" -i - make a pov include file, not a pov scene file.\n");
printf(" -t n - Make spline n thickness. (default 1.0)\n");
printf(" -n n - Use n points per control point. (default 5)\n");
printf(" -p n - Degree of polynomial (2-6, default 4)\n");
printf("\ninfile should contain only a list of x,y,z points to influence the b-spline.\n\n");
exit(2);
}
if (c == 'p') {
degree = atoi(optarg);
if (degree < 2 || degree > 6) {
fprintf(stderr, "bspline: Invalid polynomial degree, should be in range 2-6\n");
exit(3);
}
}
if (c == 'n') {
points = atoi(optarg);
if (points < 1 || points > 1000) {
fprintf(stderr, "bspline: Invalid number of points : %d.\n", points);
exit(4);
}
}
if (c == 't') {
sscanf(optarg, "%lf", &thick);
if (thick <= 0) {
fprintf(stderr, "bspline: Invalid spline thickness.\n");
exit(5);
}
}
if (c == 'i')
include = 1;
}
fprintf(stderr, "pov-bspline version %1.1f - 1994, Michael Mittelstadt\n", VERSION);
fprintf(stderr, "Thickness : %lf\nPoints per control point : %d\n",
thick, points);
fprintf(stderr, "Polynomial Degree : %d\n", degree);
outputstuff(snarfnumbers());
}